#include"comm.hpp"
//全局变量，在对应加载的时候，会自动构建全局变量，就要调用该类的构造函数--创建管道文件
//程序退出的时候，全局变量会被析构，自动调用析构函数，会自动删除管道文件
Init init;

string TransToHex(key_t k)
{
    char buffer[32];
    snprintf(buffer,sizeof buffer,"0x%x",k);
    return buffer;
}

int main()
{
    //之前为了通信，所做的所有工作，都属为了让不同的进程看到同一份资源(内存)
    //1.创建公共的Key
    key_t k = ftok(PATH_NAME,PROJ_ID);
    assert(k != -1);
    Log("create key done",Debug) << " server key: " << TransToHex(k) << endl;

    //2.创建共享内存--建议创建一个全新的共享内存--因为他是通信的发起者
    int shmid = shmget(k,SHM_SIZE,IPC_CREAT | IPC_EXCL | 0666);

    //shmget成功则返回标识符，失败返回-1
    if(shmid == -1)
    {
        perror("shmget");
        exit(1); 
    }
    Log("create shm done",Debug) << " shmid: " << shmid << endl;
    // sleep(10);

    //3.将指定的共享内存挂接到自己的地址空间
    //shmat函数，如果成功则返回一个与你挂接的addr，，这个地址一定是虚拟地址，失败则返回-1，并且错误码也被设置
    char *shmaddr = (char*)shmat(shmid,nullptr,0);
    Log("attach shm done",Debug) << " shmid: " << shmid << endl;
    // sleep(10);

    //这里是通信的逻辑
    //将共享内存当成一个大字符串
    //char buffer[SHM_SIZE];
    //结论1：只有是通信双方使用shm，一方直接向共享内存中写入数据，另一方，就可以立马看到对方写入的数据
    //共享内存是所有进程间通信(IPC),速度最快的！不需要过多的拷贝(不需要将数据给操作系统)
    //结论2：共享内存缺乏访问控制，会带来并发问题【如果我想一定的程度控制呢？能做到】

    int fd = OpenFIFO(FIFO_NAME,READ);

    for(;;)
    {
        Wait(fd);

        printf("%s\n",shmaddr);
        if(strcmp(shmaddr,"quit") == 0) break;
        //sleep(1);
    }
    
    //4.将指定的共享内存，从自己的地址空间中去关联
    //shmdt,成功0，失败1
    int n = shmdt(shmaddr);
    assert(n != -1);
    (void)n;
    Log("detach shmid done",Debug) << " shmid: " << shmid << endl;
    // sleep(10);

    //5.删除共享内存
    //IPC_RMID:即便是有进程和当下的shm挂接，依旧删除共享内存
    n = shmctl(shmid,IPC_RMID,nullptr);
    assert(n != -1);
    (void)n;
    Log("delete shmid done",Debug) << " shmid: " << shmid << endl;
    CloseFifo(fd);

    return 0;
}